﻿using Inaction.Mapping;
using System;
using System.ComponentModel;
using System.Data;

namespace Inaction.Core
{
    [Serializable]
    public abstract class ModelBase : IDbQuerable
    {
        #region 属性
        #region abstract
        public abstract Guid? PrimaryKey { get; }
        internal protected abstract void Init(IDataReader reader);

        #region CheckError
        public virtual bool CheckError(out string error, System.Data.IDbTransaction trans = null)
        {
            error = string.Empty;           
            var classInfo = ClassInfo.LoadInfo(this.GetType());
            foreach (var property in classInfo.Properties )
            {
                var s = string.Empty;
                if (CheckPropertyError(out s, property, trans))
                {
                    if (!string.IsNullOrEmpty(error)) error += Environment.NewLine;
                    error += s;
                }
            }
            return !string.IsNullOrEmpty(error);
        }
        public virtual bool CheckPropertyError(out string error, IProperty property, System.Data.IDbTransaction trans = null)
        {
            error = string.Empty;
            var val = property.GetFieldValue(this);
            if (property.Required != null)
            {
                if (!property.Required.IsValid(val))
                {
                    error = property.Required.FormatErrorMessage(property.DisplayName) + Environment.NewLine;
                }
            }
            if (val != null)
            {
                foreach (var validate in property.ValidateAttributes)
                {
                    if (!validate.IsValid(val))
                    {
                        error = validate.FormatErrorMessage(property.DisplayName) + Environment.NewLine;
                    }
                }
            }
            return !string.IsNullOrEmpty(error);
        }

        public virtual bool CheckPropertyError(out string error, string propertyName, System.Data.IDbTransaction trans = null)
        {
            error = string.Empty;
            var classInfo = ClassInfo.LoadInfo(this.GetType());
            if (classInfo.NameProperties.ContainsKey(propertyName))
            {
                var property = classInfo.NameProperties[propertyName];
                return CheckPropertyError(out error, property);
            }
            return false;
        }
        #endregion

        #endregion

        #endregion

        #region  SetProperty
        protected virtual void SetProperty<P>(Property<P> property, ref P field, P newValue)
        {
            if (newValue == null && field == null) return;
            else if (field != null && field.Equals(newValue)) return;
            field = newValue;
        }

        #endregion

        #region 方法
        public abstract bool IsDirty { get; }
        public abstract bool IsSelfDirty { get; }
        public abstract bool IsPropertyDirty(IProperty property);
        #endregion

        #region IDbQuerable
        [Browsable(false)]
        public string ParaFix
        {
            get { return Inaction.DbProvider.Instance.ParaFix; }
        }
        #endregion
    }
}
